package com.cloudJeesite.framework.frameworkCore.common.uitls.json;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.PropertyFilter;

/**
 * Created by timo on 2017/11/7.
 */
public class JsonUtil {
    /**
     * 转json为单个对象
     * @param jsonString
     * @param prototype
     * @return
     * @throws IOException
     * @throws JsonMappingException
     * @throws JsonParseException
     */
    public static <T> T getEntity(String jsonString, Class<T> prototype) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);//忽略不需要的字段
        return (T) objectMapper.readValue(jsonString, prototype);
    }
    /**
     * 将List<T>的JSON字符串反转为泛型
     *  List<User> list = readJson(json, List.class, User.class);
     * @return
     * @throws IOException
     * @throws JsonMappingException
     * @throws JsonParseException
     */
    public static <T> T getEntitys(String jsonStr,Class<T> collectionClass, Class<?>... elementClasses) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
        return objectMapper.readValue(jsonStr, javaType);
    }

    /**
     * 转换数据为 List<Map<String, Object>>
     * @param list 数据
     * @param nameLi	映射字段
     * @return
     * @throws Exception
     */
    public static List<Map<String, Object>> castEntity(List<Object[]> list, String[] nameLi)  {
        List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = new HashMap<String, Object>();
            for(int j = 0;j < nameLi.length; j ++){
                map.put(nameLi[j], ((Object[])list.get(i))[j]);
            }
            returnList.add(map);
        }
        return returnList;
    }
    /**
     * 转换数据为 Map<String, Object>
     * @param obj 数据
     * @param nameLi	映射字段
     * @return
     * @throws Exception
     */
    public static Map<String, Object> castEntity(Object[] obj,String[] nameLi)  {
        Map<String, Object> map = new HashMap<String, Object>();
        for(int j = 0;j < nameLi.length; j ++){
            map.put(nameLi[j],obj[j]);
        }
        return map;
    }
    public static Map<String, Object> castEntity(Object obj,String[] nameLi)  {
        Object[] objs = (Object[]) obj;
        Map<String, Object> map = new HashMap<String, Object>();
        for(int j = 0;j < nameLi.length; j ++){
            map.put(nameLi[j],objs[j]);
        }
        return map;
    }

    //提供了一个过滤作用，如果遇到关联的对象时他会自动过滤掉，不去执行关联关联所关联的对象。
//    JsonConfig config = new JsonConfig();
//    config.setExcludes( new String[]{ "shops" ,"comments" } ) ;//在这里添加要过滤的属性名
//    JSONObject jsonObject = JSONObject.fromObject(userList,config); //这里需要加载过滤


    /**
     * 将对象转化为json输出
     * @param obj
     * @return
     * @throws JsonProcessingException
     */
    public static String writeValueAsString(Object obj) throws JsonProcessingException {
        ObjectMapper om = new ObjectMapper();
        return om.writeValueAsString(obj);
    }
    /**
     * <li>将对象转化为json输出
     * <li>QuoteFieldNames ———-输出key时是否使用双引号,默认为true
     * <li>WriteMapNullValue ——–是否输出值为null的字段,默认为false
     * <li>WriteNullNumberAsZero —-数值字段如果为null,输出为0,而非null
     * <li>WriteNullListAsEmpty —–List字段如果为null,输出为[],而非null
     * <li>WriteNullStringAsEmpty —字符类型字段如果为null,输出为”“,而非null
     * <li>WriteNullBooleanAsFalse –Boolean字段如果为null,输出为false,而非null
     */
    public static String objToJson(Object obj){
        SerializerFeature[] serializerFeaturess = {
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullNumberAsZero,
                SerializerFeature.WriteNullListAsEmpty,
                SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.WriteNullBooleanAsFalse,
                SerializerFeature.WriteDateUseDateFormat,
                SerializerFeature.IgnoreNonFieldGetter
        };
        return JSON.toJSONString(obj,serializerFeaturess);
    }


//     List<MagazineModel> magas=paperService.findParentMagzines();//用hibernate 得到MagazineModel
//        List<String> strings=new ArrayList<>();                                                 //设置要过滤的属性
//        strings.add("magazines");
//        strings.add("magazine");
//        strings.add("papers");
//       ConvertToJSON.modelBeanToJSON(strings, magas)                 //调用输出的结果是[{"descript":"","id":1,"name":"SCI","score":0},{"descript":"","id":2,"name":"EI","score":0}]
    public static String modelBeanToJSON(final String[] filterField, List<?> list){
        JSONArray jsonObjects = new JSONArray();
        int i=0;
        Iterator<?> it = list.iterator();
        while(it.hasNext()){
            JSONObject jsonObject = new JSONObject();
            Object obj = it.next();//这里的Obj对象只是list中的存放的对象类型
            JsonConfig jsonConfig = new JsonConfig();
            PropertyFilter filter = new PropertyFilter() {
                public boolean apply(Object source, String name, Object value) {
                    boolean isFiltered=false;
                    for(String string:filterField){
                        if(string.equals(name)){
                            isFiltered=true;
                        }
                    }
                    if (isFiltered) {
                        return true;
                    }
                    return false;
                }
            };
            jsonConfig.setJsonPropertyFilter(filter);

            jsonObject= JSONObject.fromObject(obj, jsonConfig);
            jsonObjects.add(i++, jsonObject);
        }
        return jsonObjects.toString();
    }

    public static Gson gson1= null;
    public static Gson gson2= null;
    public static Gson gson3= null;
    public static Gson publicGson= null;

    static {
//        TargetStrategy ts = new TargetStrategy(Student.class);
////这里表示仅转换Student中的id和name属性
//        ts.setFields(new String[] {"id", "name"});
//        ts.setReverse(true);
        publicGson = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
                .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
                .setDateFormat("yyyy-MM-dd HH:mm:ss")//时间转化为特定格式
                .setVersion(20.0)//用于排除字段
                .registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
                .create();


        gson1 = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
                .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
//                .serializeNulls()//为空不参与序列化
                .setDateFormat("yyyy-MM-dd HH:mm:ss")//时间转化为特定格式
//                .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//会把字段首字母大写,注:对于实体上使用了@SerializedName注解的不会生效.
//                .setPrettyPrinting() //对json结果格式化.
                .setVersion(1.0)
                //有的字段不是一开始就有的,会随着版本的升级添加进来,那么在进行序列化和返序列化的时候就会根据版本号来选择是否要序列化.
                //@Since(版本号)能完美地实现这个功能.还的字段可能,随着版本的升级而删除,那么
                //@Until(版本号)也能实现这个功能,GsonBuilder.setVersion(double)方法需要调用.

//                .setExclusionStrategies(ts)
                .registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
                .create();

        gson2 = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
                .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
//                .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")//时间转化为特定格式
                .setVersion(2.0)
                .registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
                .create();
        gson3 = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
                .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
                .setDateFormat("yyyy-MM-dd HH:mm:ss")//时间转化为特定格式
                .setVersion(3.0)
                .registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
                .create();

//        new GsonBuilder().setExcludeStrategy(ts).create();
    }



    @SuppressWarnings("unused")
	public static void main(String[] args) {
//注意这里的Gson的构建方式为GsonBuilder,区别于test1中的Gson gson = new Gson();
        Gson gson = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
                .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
                .serializeNulls().setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")//时间转化为特定格式
                .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//会把字段首字母大写,注:对于实体上使用了@SerializedName注解的不会生效.
                .setPrettyPrinting() //对json结果格式化.
                .setVersion(1.0)    //有的字段不是一开始就有的,会随着版本的升级添加进来,那么在进行序列化和返序列化的时候就会根据版本号来选择是否要序列化.
                //@Since(版本号)能完美地实现这个功能.还的字段可能,随着版本的升级而删除,那么
                //@Until(版本号)也能实现这个功能,GsonBuilder.setVersion(double)方法需要调用.
                .create();



//        Student student1 = new Student();
//        student1.setId(1);
//        student1.setName("李坤");
//        student1.setBirthDay(new Date());
//
//        // //////////////////////////////////////////////////////////
//        System.out.println("----------简单对象之间的转化-------------");
//        // 简单的bean转为json
//        String s1 = gson.toJson(student1);
//        System.out.println("简单Bean转化为Json===" + s1);
//
//        // json转为简单Bean
//        Student student = gson.fromJson(s1, Student.class);
//        System.out.println("Json转为简单Bean===" + student);
//        // //////////////////////////////////////////////////////////
//
//        Student student2 = new Student();
//        student2.setId(2);
//        student2.setName("曹贵生");
//        student2.setBirthDay(new Date());
//
//        Student student3 = new Student();
//        student3.setId(3);
//        student3.setName("柳波");
//        student3.setBirthDay(new Date());
//
//        List<Student> list = new ArrayList<Student>();
//        list.add(student1);
//        list.add(student2);
//        list.add(student3);
//
//        System.out.println("----------带泛型的List之间的转化-------------");
//        // 带泛型的list转化为json
//        String s2 = gson.toJson(list);
//        System.out.println("带泛型的list转化为json==" + s2);
//
//        // json转为带泛型的list
//        List<Student> retList = gson.fromJson(s2,
//                new TypeToken<List<Student>>() {
//                }.getType());
//        for (Student stu : retList) {
//            System.out.println(stu);
//        }
    }
}
